FlaskãDjangoãFastAPIã®Webãã¬ãŒã ã¯ãŒã¯ã®ããã©ãŒãã³ã¹ãæ¯èŒããå æ¬çãªãã³ãããŒã¯ãé床ããªãœãŒã¹äœ¿çšéãããŸããŸãªã¢ããªã±ãŒã·ã§ã³ã¿ã€ããžã®é©åæ§ãåæããŸãã
Webãã¬ãŒã ã¯ãŒã¯ã®ããã©ãŒãã³ã¹ïŒFlask vs Django vs FastAPI ãã³ãããŒã¯
å¹ççã§ã¹ã±ãŒã©ãã«ãªWebã¢ããªã±ãŒã·ã§ã³ãæ§ç¯ããã«ã¯ãé©åãªWebãã¬ãŒã ã¯ãŒã¯ãéžæããããšãéèŠã§ããPythonã«ã¯ãããããã«é·æãšçæãããåªããéžæè¢ãããã€ããããŸãããã®èšäºã§ã¯ã人æ°ã®ãã3ã€ã®ãã¬ãŒã ã¯ãŒã¯ãFlaskãDjangoãFastAPIãæ¯èŒããå æ¬çãªãã³ãããŒã¯ãæäŸããŸããã°ããŒãã«ãªéçºãã©ã¯ãã£ã¹ãšãããã€ã¡ã³ãç°å¢ãèæ ®ãããããã®ããã©ãŒãã³ã¹ç¹æ§ããªãœãŒã¹äœ¿çšéãããŸããŸãªã¢ããªã±ãŒã·ã§ã³ã¿ã€ããžã®é©åæ§ãåæããŸãã
ã¯ããã«
Webãã¬ãŒã ã¯ãŒã¯ã¯ãã«ãŒãã£ã³ã°ããªã¯ãšã¹ãåŠçãããŒã¿ããŒã¹æäœãªã©ã®ã¿ã¹ã¯ãåŠçããWebã¢ããªã±ãŒã·ã§ã³ãæ§ç¯ããããã®æ§é åãããç°å¢ãæäŸããŸãããã¬ãŒã ã¯ãŒã¯ã®éžæã¯ãç¹ã«é«è² è·äžã§ã®ã¢ããªã±ãŒã·ã§ã³ã®ããã©ãŒãã³ã¹ã«å€§ãã圱é¿ããŸãããã®ãã³ãããŒã¯ã¯ãéçºè ãæ å ±ã«åºã¥ããæææ±ºå®ãè¡ãã®ã«åœ¹ç«ã€ãããŒã¿ã«åºã¥ããæŽå¯ãæäŸããããšãç®çãšããŠããŸãã
- Flask: ã·ã³ãã«ããšæè»æ§ãæäŸãããã€ã¯ããã¬ãŒã ã¯ãŒã¯ã§ãããã现ããªå¶åŸ¡ãå¿ èŠãªå°èŠæš¡ããäžèŠæš¡ã®ãããžã§ã¯ãã«é©ããŠããŸãã
- Django: ORMããã³ãã¬ãŒããšã³ãžã³ã管çã€ã³ã¿ãŒãã§ãŒã¹ãªã©ãå æ¬çãªããŒã«ãšæ©èœãæäŸãããã«æ©èœã®ãã¬ãŒã ã¯ãŒã¯ã§ããå ç¢ã§ã¹ã±ãŒã©ãã«ãªã¢ãŒããã¯ãã£ãå¿ èŠãšããè€éãªã¢ããªã±ãŒã·ã§ã³ã«é©ããŠããŸãã
- FastAPI: ASGIäžã«æ§ç¯ããããé«éãã€å¹ççã«APIãæ§ç¯ããããã«èšèšããããã¢ãã³ã§é«æ§èœãªãã¬ãŒã ã¯ãŒã¯ã§ããéåææäœã«åªããŠããããã€ã¯ããµãŒãã¹ãé«ã¹ã«ãŒãããã®ã¢ããªã±ãŒã·ã§ã³ã«ãšã£ãŠåŒ·åãªåè£ã§ãã
ãã³ãããŒã¯ã®ã»ããã¢ãã
å ¬æ£ãã€æ£ç¢ºãªæ¯èŒãä¿èšŒããããã«ãæšæºåããããã³ãããŒã¯ã»ããã¢ããã䜿çšããŸããããã«ã¯ä»¥äžãå«ãŸããŸãïŒ
- ããŒããŠã§ã¢: äžè²«ãã仿§ïŒCPUãRAMãã¹ãã¬ãŒãžãªã©ïŒãæã€å°çšãµãŒããŒãæ£ç¢ºãªä»æ§ã¯ãªã¹ãåããããã¹ãå šäœã§äžå®ã«ä¿ãããŸãã
- ãœãããŠã§ã¢: PythonãFlaskãDjangoãFastAPIã®ææ°å®å®ããŒãžã§ã³ãWSGI/ASGIãµãŒããŒã«ã¯GunicornãšUvicornã®äžè²«ããããŒãžã§ã³ã䜿çšããŸãã
- ããŒã¿ããŒã¹: æé©ãªããã©ãŒãã³ã¹ãçºæ®ããããã«æ§æãããã人æ°ã®ãªãŒãã³ãœãŒã¹ãªã¬ãŒã·ã§ãã«ããŒã¿ããŒã¹ã§ããPostgreSQLã
- è² è·ãã¹ãããŒã«: åææ¥ç¶ãŠãŒã¶ãŒãã·ãã¥ã¬ãŒãããã¢ããªã±ãŒã·ã§ã³ã®ããã©ãŒãã³ã¹ã枬å®ããããã«äœ¿çšããããPythonããŒã¹ã®è² è·ãã¹ãããŒã«ã§ããLocustã
- ã¢ãã¿ãªã³ã°ããŒã«: ãµãŒããŒã®ãªãœãŒã¹äœ¿çšéïŒCPUãã¡ã¢ãªããããã¯ãŒã¯ïŒãç£èŠããããã®PrometheusãšGrafanaã
- ãã¹ãã±ãŒã¹: äžè¬çãªWebã¢ããªã±ãŒã·ã§ã³ã®ã·ããªãªã代衚ããããã€ãã®ãã¹ãã±ãŒã¹ãå®çŸ©ããŸãïŒ
- Hello World: éçãªæååãè¿ãåçŽãªãšã³ããã€ã³ããããã¯ãã¬ãŒã ã¯ãŒã¯ã®åºæ¬çãªã«ãŒãã£ã³ã°ãšãªã¯ãšã¹ãåŠçã®ãªãŒããŒãããããã¹ãããŸãã
- ããŒã¿ããŒã¹èªã¿åã: ããŒã¿ããŒã¹ããããŒã¿ãååŸãããšã³ããã€ã³ããããã¯ãã¬ãŒã ã¯ãŒã¯ã®ORMïŒãŸãã¯ããŒã¿ããŒã¹æäœã¬ã€ã€ãŒïŒã®ããã©ãŒãã³ã¹ããã¹ãããŸãã
- ããŒã¿ããŒã¹æžã蟌ã¿: ããŒã¿ããŒã¹ã«ããŒã¿ãæžã蟌ããšã³ããã€ã³ããããã¯æžãèŸŒã¿æäœäžã®ãã¬ãŒã ã¯ãŒã¯ã®ORMïŒãŸãã¯ããŒã¿ããŒã¹æäœã¬ã€ã€ãŒïŒã®ããã©ãŒãã³ã¹ããã¹ãããŸãã
- JSONã·ãªã¢ã©ã€ãŒãŒã·ã§ã³: ããŒã¿ãJSON圢åŒã«ã·ãªã¢ã©ã€ãºãããšã³ããã€ã³ããããã¯ãã¬ãŒã ã¯ãŒã¯ã®ã·ãªã¢ã©ã€ãŒãŒã·ã§ã³ããã©ãŒãã³ã¹ããã¹ãããŸãã
ãã³ãããŒã¯ç°å¢ã®æ§æè©³çް
- CPU: Intel Xeon E3-1231 v3 @ 3.40GHz
- RAM: 16GB DDR3
- ã¹ãã¬ãŒãž: 256GB SSD
- ãªãã¬ãŒãã£ã³ã°ã·ã¹ãã : Ubuntu 20.04
- Python: 3.9.7
- Flask: 2.0.1
- Django: 3.2.8
- FastAPI: 0.68.1
- Uvicorn: 0.15.0
- Gunicorn: 20.1.0
- PostgreSQL: 13.4
åææ¥ç¶ã¬ãã«: ããã©ãŒãã³ã¹ã培åºçã«è©äŸ¡ããããã10ãã500ã®åææ¥ç¶ãŠãŒã¶ãŒã®ç¯å²ã§ãããŸããŸãªåææ¥ç¶ã¬ãã«ã§åãã¬ãŒã ã¯ãŒã¯ããã¹ãããŸããããã«ãããè² è·ãå¢å ããã«ã€ããŠåãã¬ãŒã ã¯ãŒã¯ãã©ã®ããã«ã¹ã±ãŒã«ãããã芳å¯ã§ããŸãã
ãã¬ãŒã ã¯ãŒã¯ã®å®è£
åãã¬ãŒã ã¯ãŒã¯ã«ã€ããŠãäžèšã®ãã¹ãã±ãŒã¹ãå®è£ ããã·ã³ãã«ãªã¢ããªã±ãŒã·ã§ã³ãäœæããŸãã
Flask
Flaskã¯Werkzeug WSGIããŒã«ãããã䜿çšããŸããããŒã¿ããŒã¹æäœã«ã¯ã人æ°ã®ããORMã§ããSQLAlchemyã䜿çšããŸãã以äžã¯ç°¡ç¥åãããäŸã§ãïŒ
from flask import Flask, jsonify
from sqlalchemy import create_engine, Column, Integer, String
from sqlalchemy.orm import sessionmaker
from sqlalchemy.ext.declarative import declarative_base
app = Flask(__name__)
engine = create_engine('postgresql://user:password@host:port/database')
Base = declarative_base()
class Item(Base):
__tablename__ = 'items'
id = Column(Integer, primary_key=True)
name = Column(String)
Base.metadata.create_all(engine)
Session = sessionmaker(bind=engine)
session = Session()
@app.route('/hello')
def hello_world():
return 'Hello, World!'
@app.route('/item/')
def get_item(item_id):
item = session.query(Item).get(item_id)
if item:
return jsonify({'id': item.id, 'name': item.name})
else:
return 'Item not found', 404
if __name__ == '__main__':
app.run(debug=True)
Django
Djangoã¯çµã¿èŸŒã¿ã®ORMãšãã³ãã¬ãŒããšã³ãžã³ã䜿çšããŸãã以äžã¯ç°¡ç¥åãããäŸã§ãïŒ
from django.http import JsonResponse, HttpResponse
from django.shortcuts import get_object_or_404
from django.db import models
class Item(models.Model):
name = models.CharField(max_length=255)
def hello_world(request):
return HttpResponse('Hello, World!')
def get_item(request, item_id):
item = get_object_or_404(Item, pk=item_id)
return JsonResponse({'id': item.id, 'name': item.name})
FastAPI
FastAPIã¯ASGIäžã«æ§ç¯ãããŠãããããŒã¿æ€èšŒã«Pydanticã䜿çšããŸããããŒã¿ããŒã¹æäœã«ã¯SQLAlchemyã䜿çšããŸãããã€ãã£ãã§éåæãªã¯ãšã¹ãåŠçããµããŒãããŠããŸãã
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel
from typing import Optional
from sqlalchemy import create_engine, Column, Integer, String
from sqlalchemy.orm import sessionmaker
from sqlalchemy.ext.declarative import declarative_base
app = FastAPI()
engine = create_engine('postgresql://user:password@host:port/database')
Base = declarative_base()
class Item(Base):
__tablename__ = 'items'
id = Column(Integer, primary_key=True)
name = Column(String)
Base.metadata.create_all(engine)
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
def get_db():
db = SessionLocal()
try:
yield db
finally:
db.close()
class ItemSchema(BaseModel):
id: int
name: str
@app.get('/hello')
async def hello_world():
return 'Hello, World!'
@app.get('/item/{item_id}', response_model=ItemSchema)
async def read_item(item_id: int, db: SessionLocal = Depends(get_db)):
item = db.query(Item).filter(Item.id == item_id).first()
if item is None:
raise HTTPException(status_code=404, detail='Item not found')
return item
ãã³ãããŒã¯çµæ
以äžã®è¡šã¯ãåãã¹ãã±ãŒã¹ã®ãã³ãããŒã¯çµæããŸãšãããã®ã§ããçµæã¯ã1ç§ãããã®ãªã¯ãšã¹ãæ°ïŒRPSïŒãšå¹³åã¬ã€ãã³ã·ïŒããªç§ïŒã§ç€ºãããŠããŸãã
Hello World
| ãã¬ãŒã ã¯ãŒã¯ | åææ¥ç¶æ° | RPS | ã¬ã€ãã³ã· (ms) |
|---|---|---|---|
| Flask | 100 | X | Y |
| Django | 100 | A | B |
| FastAPI | 100 | P | Q |
| Flask | 500 | Z | W |
| Django | 500 | C | D |
| FastAPI | 500 | R | S |
ããŒã¿ããŒã¹èªã¿åã
| ãã¬ãŒã ã¯ãŒã¯ | åææ¥ç¶æ° | RPS | ã¬ã€ãã³ã· (ms) |
|---|---|---|---|
| Flask | 100 | U | V |
| Django | 100 | E | F |
| FastAPI | 100 | T | U |
| Flask | 500 | NN | OO |
| Django | 500 | G | H |
| FastAPI | 500 | VV | XX |
ããŒã¿ããŒã¹æžã蟌ã¿
| ãã¬ãŒã ã¯ãŒã¯ | åææ¥ç¶æ° | RPS | ã¬ã€ãã³ã· (ms) |
|---|---|---|---|
| Flask | 100 | KK | LL |
| Django | 100 | I | J |
| FastAPI | 100 | YY | ZZ |
| Flask | 500 | MMM | PPP |
| Django | 500 | K | L |
| FastAPI | 500 | AAA | BBB |
JSONã·ãªã¢ã©ã€ãŒãŒã·ã§ã³
| ãã¬ãŒã ã¯ãŒã¯ | åææ¥ç¶æ° | RPS | ã¬ã€ãã³ã· (ms) |
|---|---|---|---|
| Flask | 100 | RR | |
| Django | 100 | M | N |
| FastAPI | 100 | CCC | DDD |
| Flask | 500 | SSS | TTT |
| Django | 500 | O | P |
| FastAPI | 500 | EEE | FFF |
泚: ãã¬ãŒã¹ãã«ããŒå€ïŒXãYãAãBãªã©ïŒã¯ããã¹ããå®è¡ããŠåŸãããå®éã®ãã³ãããŒã¯çµæã«çœ®ãæããŠãã ããããããã®çµæã¯ãlocustããã®ä»ã®ç£èŠããŒã«ã䜿çšããŠãã¹ããå®è¡ããåŸã«èšå®ãããŸãã
åæãšè§£é
ãã³ãããŒã¯çµæïŒãã¬ãŒã¹ãã«ããŒãå®éã®ããŒã¿ã«çœ®ãæããŠãã ããïŒã«åºã¥ãã以äžã®çµè«ãå°ãåºãããšãã§ããŸãïŒ
- FastAPIã¯äžè¬çã«ãç¹ã«é«ãåææ¥ç¶äžã§ãRPSãšã¬ã€ãã³ã·ã®ç¹ã§FlaskãšDjangoãäžåããŸããããã¯ããã®éåææ§ãšPydanticã䜿çšããæé©åãããããŒã¿æ€èšŒã«ãããã®ã§ãã
- Flaskã¯ããã©ãŒãã³ã¹ãšæè»æ§ã®ãã©ã³ã¹ãåããŠããŸããå°èŠæš¡ãªãããžã§ã¯ãããã¢ããªã±ãŒã·ã§ã³ã¢ãŒããã¯ãã£ã«å¯ŸããŠãã现ããªå¶åŸ¡ãå¿ èŠãªå Žåã«é©ããéžæè¢ã§ãã
- Djangoã¯ãã«æ©èœã®ãã¬ãŒã ã¯ãŒã¯ã§ããäžæ¹ãç¹ã«APIäžå¿ã®ã¢ããªã±ãŒã·ã§ã³ã§ã¯FastAPIã«æ¯ã¹ãŠããã©ãŒãã³ã¹ãäœãå ŽåããããŸããããããè€éãªãããžã§ã¯ãã®éçºãç°¡çŽ åã§ããè±å¯ãªæ©èœãšããŒã«ãæäŸããŸãã
- ããŒã¿ããŒã¹æäœã¯ããã¬ãŒã ã¯ãŒã¯ã«é¢ä¿ãªãããã«ããã¯ã«ãªãå¯èœæ§ããããŸããããŒã¿ããŒã¹ã¯ãšãªãæé©åãããã£ãã·ã¥ã¡ã«ããºã ã䜿çšããããšã§ãããã©ãŒãã³ã¹ãå€§å¹ ã«åäžãããããšãã§ããŸãã
- JSONã·ãªã¢ã©ã€ãŒãŒã·ã§ã³ã®ãªãŒããŒãããã¯ãç¹ã«å€§éã®ããŒã¿ãè¿ããšã³ããã€ã³ãã§ããã©ãŒãã³ã¹ã«åœ±é¿ãäžããå¯èœæ§ããããŸããå¹ççãªã·ãªã¢ã©ã€ãŒãŒã·ã§ã³ã©ã€ãã©ãªãšãã¯ããã¯ã䜿çšããããšã§ãããã軜æžã§ããŸãã
ã°ããŒãã«ãªèæ ®äºé ãšãããã€ã¡ã³ã
Webã¢ããªã±ãŒã·ã§ã³ãã°ããŒãã«ã«ãããã€ããéã«ã¯ã以äžã®èŠçŽ ãèæ ®ããŠãã ããïŒ
- å°ççååž: ã³ã³ãã³ãããªããªãŒãããã¯ãŒã¯ïŒCDNïŒã䜿çšããŠéçã¢ã»ããããã£ãã·ã¥ããç°ãªãå°åã®ãŠãŒã¶ãŒã®ã¬ã€ãã³ã·ãåæžããŸãã
- ããŒã¿ããŒã¹ã®å Žæ: ãŠãŒã¶ãŒã®å€§å€æ°ã«å°ççã«è¿ãããŒã¿ããŒã¹ã®å ŽæãéžæããŸãã
- ã¿ã€ã ãŸãŒã³: ã¿ã€ã ãŸãŒã³ãæ£ããåŠçããç°ãªãå°åã®ãŠãŒã¶ãŒã«å¯ŸããŠæ¥ä»ãšæå»ãæ£ç¢ºã«è¡šç€ºãããããã«ããŸããpytzã®ãããªã©ã€ãã©ãªãäžå¯æ¬ ã§ãã
- ããŒã«ã©ã€ãŒãŒã·ã§ã³ãšåœéå: è€æ°ã®èšèªãšæåããµããŒãããããã«ãããŒã«ã©ã€ãŒãŒã·ã§ã³ãšåœéåïŒi18n/l10nïŒãå®è£ ããŸããDjangoã«ã¯çµã¿èŸŒã¿ã®ãµããŒãããããFlaskã«ã¯Flask-Babelã®ãããªæ¡åŒµæ©èœããããŸãã
- é貚ã®åãæ±ã: ãã©ãŒããããæç®ã¬ãŒããå«ããç°ãªãéè²šãæ£ããåŠçããããã«ããŸãã
- ããŒã¿ãã©ã€ãã·ãŒèŠå¶: ã¿ãŒã²ãããªãŒãã£ãšã³ã¹ã«å¿ããŠãGDPRïŒãšãŒãããïŒãCCPAïŒã«ãªãã©ã«ãã¢ïŒãªã©ã®ããŒã¿ãã©ã€ãã·ãŒèŠå¶ã«æºæ ããŸãã
- ã¹ã±ãŒã©ããªãã£: ç°ãªãå°åããã®å¢å ãããã©ãã£ãã¯ãåŠçããããã«ãã¢ããªã±ãŒã·ã§ã³ãæ°Žå¹³æ¹åã«ã¹ã±ãŒã«ã§ããããã«èšèšããŸããã³ã³ããåïŒDockerïŒãšãªãŒã±ã¹ãã¬ãŒã·ã§ã³ïŒKubernetesïŒãäžè¬çãªææ³ã§ãã
- ç£èŠãšãã®ã³ã°: å æ¬çãªç£èŠãšãã®ã³ã°ãå®è£ ããã¢ããªã±ãŒã·ã§ã³ã®ããã©ãŒãã³ã¹ã远跡ããç°ãªãå°åã§ã®åé¡ãç¹å®ããŸãã
äŸãã°ããã€ãã«æ ç¹ã眮ãããšãŒããããšåç±³ã®äž¡æ¹ã®é¡§å®¢ã«ãµãŒãã¹ãæäŸããŠããäŒæ¥ã¯ãäž¡å°åã«ãšããžãã±ãŒã·ã§ã³ãæã€CDNã®äœ¿çšããŠãŒã¶ãŒããŒã¹ã«å°ççã«è¿ãå°åïŒäŸïŒã¢ã€ã«ã©ã³ããç±³åœæ±æµ·å²žïŒã§ã®ããŒã¿ããŒã¹ãã¹ãã£ã³ã°ããããŠè±èªãšãã€ãèªããµããŒãããããã®i18n/l10nã®å®è£ ãæ€èšãã¹ãã§ãããŸããã¢ããªã±ãŒã·ã§ã³ãGDPRããã³é©çšãããç±³åœã®å·ãã©ã€ãã·ãŒæ³ã«æºæ ããŠããããšã確èªããå¿ èŠããããŸãã
çµè«
Webãã¬ãŒã ã¯ãŒã¯ã®éžæã¯ããããžã§ã¯ãã®ç¹å®ã®èŠä»¶ã«äŸåããŸããFastAPIã¯APIäžå¿ã®ã¢ããªã±ãŒã·ã§ã³ã«åªããããã©ãŒãã³ã¹ãæäŸããFlaskã¯æè»æ§ãšã·ã³ãã«ããæäŸããŸããDjangoã¯è€éãªãããžã§ã¯ãã«é©ããå ç¢ãªãã«æ©èœã®ãã¬ãŒã ã¯ãŒã¯ã§ãããããžã§ã¯ãã®èŠä»¶ã培åºçã«è©äŸ¡ãããã®èšäºã§æç€ºããããã³ãããŒã¯çµæãèæ ®ããŠãæ å ±ã«åºã¥ããæææ±ºå®ãè¡ã£ãŠãã ããã
å®è·µçãªæŽå¯
- ç¬èªã®ãã³ãããŒã¯ãå®è¡ãã: ãããã®ãã¹ããç¹å®ã®ãŠãŒã¹ã±ãŒã¹ãšã€ã³ãã©ã¹ãã©ã¯ãã£ã«åãããŠèª¿æŽããŠãã ããã
- éåæã¿ã¹ã¯ãæ€èšãã: é·æéå®è¡ãããã¿ã¹ã¯ãããå Žåã¯ãCeleryã®ãããªéåæã¿ã¹ã¯ãã¥ãŒã䜿çšããŠãã ããã
- ããŒã¿ããŒã¹ã¯ãšãªãæé©åãã: ã€ã³ããã¯ã¹ããã£ãã·ã³ã°ãå¹ççãªã¯ãšãªèšèšã䜿çšããŠãã ããã
- ã¢ããªã±ãŒã·ã§ã³ããããã¡ã€ãªã³ã°ãã: ãããã¡ã€ãªã³ã°ããŒã«ã䜿çšããŠããã«ããã¯ãç¹å®ããŠãã ããã
- ããã©ãŒãã³ã¹ãç£èŠãã: æ¬çªç°å¢ã§ã®ã¢ããªã±ãŒã·ã§ã³ã®ããã©ãŒãã³ã¹ã宿çã«ç£èŠããŠãã ããã